/*********************************************************************************
 *      Copyright:  (C) 2020 YangZhengQing<2489833081@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  receive_data.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(04/08/2020)
 *         Author:  YangZhengQing <2489833081@qq.com>
 *      ChangeLog:  1, Release initial version on "04/08/2020 04:25:19 PM"
 *                 
 ********************************************************************************/

#include "../include/server.h"

#define BUFFSIZE 100
/*功能：接收数据
 *参数：fd：传入文件描述符
        buff：传出接收到的数据
  返回值：成功返回接收的字节数，失败返回-1*/

int receive_data(int fd,char *buff,int size)
{
    int                 rv = -1;
    int                 current_size = 0;
    int                 i = 0;

    do 
    {
        rv = wait_timeout(fd,2);//设置超时两秒
        if(rv < 0)
        {
            printf("Read timeout error:%s\n",strerror(errno));
            return -1;
        }
        else if(rv == 0)
        {
            printf("Read timeout!\n");
            return TIMEOUT;
        }
        else
        {
            rv = read(fd, &buff[current_size], size);

            if( rv < 0)
            {
                printf("server  read from client[%d] failure\n", fd);
                return -1;
            }
            else if(rv == 0)
            {
                printf("Client[%d] is disconnected!\n",fd);
                return UNLINK;
            }
            else
            {
                current_size += rv;
                printf("The server is currently receiving %d bytes data!\n",current_size);

               //判断数据包是否完整 
                for(i = 0; i < current_size; i++)
                {
                    if(buff[i] == HEAD )//检查报头,防止报头之前出现垃圾数据
                    {
                        if(current_size > current_size - i)//过滤掉报头之前的垃圾数据
                        {
                            printf("There is garbage data in the header!\n");
                            current_size -= i;
                            memmove(buff,&buff[i],current_size);
                        }
                        break;
                    }
                }
            }
        }

    }while((unsigned char)buff[current_size-1] != REAR);

     printf("server read [%d] bytes from clienfd[%d]\n",current_size,fd);

    
    return current_size;
}


/*功能：发送数据
 *参数：fd：传入文件描述符
 *      buff:传入需要发送的数据
 *返回值：成功返回0，失败返回-1*/
int send_data(int fd,char *buff)
{
    int                     rv = -1;

    rv = write(fd,buff,strlen(buff));
    if(rv < 0)
    {
        printf("Writing response information to client[%d] is failed:%s\n",fd,strerror(errno));
        return -1;
    }

    return 0;
}

ssize_t readn(int fd, void *vptr, size_t n)
{
    size_t nleft;
    ssize_t nread;
    char *ptr;

    ptr = vptr;
    nleft = n;

    while (nleft > 0) {
        if ( (nread = read(fd, ptr, nleft)) < 0) {
            if (errno == EINTR)
                nread = 0;  /*  and call read() again */
            else
                return(-1);
        } else if (nread == 0)

            break;    /*  EOF */

        nleft -= nread;
        ptr += nread;
    }

    return(n - nleft);  /*  return >= 0 */

}

//超时
int wait_timeout(int fd,unsigned seconds)
{
    struct timeval tv;
    fd_set      readset;
    int         err;

    tv.tv_sec=seconds;
    tv.tv_usec=0;

    FD_ZERO(&readset);//清空可读描述集
    FD_SET(fd,&readset);//将文件描述符添加至可读集中

    do{
        err=select(fd+1,&readset,NULL,NULL,&tv);
    }while(err<0 && errno==EINTR);

    return err;
}


